﻿//#include "stdafx.h"
#include "QrEncode.h"


#include "qr.h"
#include "qr_util.h"


QrEncode::QrEncode()
{
}


QrEncode::~QrEncode()
{
}

QrEncode& QrEncode::Instance()
{
	static QrEncode instance;
	return instance;
}

QRCode * QrEncode::InitQr(const std::string& strDataUtf8)
{
	SetErr("");
	int errcode = QR_ERR_NONE;
	// 使用过程中使用除了QR_EM_8BIT以外的mode会生成不正常的二维码，暂时不知道原因。
	int version = -1;		//  symbol version (1-40, default(-1): auto)
	int mode = QR_EM_AUTO; //QR_EM_8BIT;	// 模式
	int eclevel = QR_ECL_M;		// QR_ECL_M;	// 误差校正等级error correction level，default(-1):15%，L(0): 7%, M(1): 15%, Q(2): 25%, H(3): 30%
	int masktype = -1;		// 0 <= masktype <QR_MPT_MAX
	QRCode * qr = qrInit(version, mode, eclevel, masktype, &errcode);
	if (qr == NULL)
	{
		//printf("Err: %s", qrStrError(errcode));
		SetErr(qrStrError(errcode));
		return NULL;
	}
	// 添加需要编码的数据
	int iRes = qrAddData(qr, (const qr_byte_t*)strDataUtf8.data(), strDataUtf8.length());
	if (!iRes)
	{
		SetErr(qrGetErrorInfo(qr));
		qrDestroy(qr);
		qr = nullptr;
		return NULL;
	}
	//注意需要调用qrFinalize函数
	if (!qrFinalize(qr))
	{
		SetErr(qrGetErrorInfo(qr));
		qrDestroy(qr);
		qr = nullptr;
		return NULL;
	}
	return qr;
}

std::vector<unsigned char> QrEncode::ToQrEncode(const std::string& strDataUtf8, QrEncodeType iEncodeType, int iSeparator /*= 4*/, int iMagnifying /*= 1*/)
{
	std::vector<unsigned char> resultVec;

	QRCode * qr = InitQr(strDataUtf8);
	if (!qr)
	{
		return resultVec;
	}

	int size = 0;
	// 获取编码结果
	qr_byte_t * buffer = nullptr;
	switch (iEncodeType)
	{
	case QrEncode::QrEncodeType_BMP:
		buffer = qrSymbolToBMP(qr, iSeparator, iMagnifying, &size);
		break;
	case QrEncode::QrEncodeType_PNG:
		buffer = qrSymbolToPNG(qr, iSeparator, iMagnifying, &size);
		break;
	case QrEncode::QrEncodeType_SVG:
		buffer = qrSymbolToSVG(qr, iSeparator, iMagnifying, &size);
		break;
	case QrEncode::QrEncodeType_TIFF:
		buffer = qrSymbolToTIFF(qr, iSeparator, iMagnifying, &size);
		break;
	case QrEncode::QrEncodeType_DIGIT:
		buffer = qrSymbolToDigit(qr, iSeparator, iMagnifying, &size);
		break;
	case QrEncode::QrEncodeType_PBM:
		buffer = qrSymbolToPBM(qr, iSeparator, iMagnifying, &size);
		break;
	case QrEncode::QrEncodeType_ASCII:
		buffer = qrSymbolToASCII(qr, iSeparator, iMagnifying, &size);
		break;
	case QrEncode::QrEncodeType_JSON:
		buffer = qrSymbolToJSON(qr, iSeparator, iMagnifying, &size);
		break;
	default:
		break;
	}

	if (!buffer)
	{
		SetErr(qrGetErrorInfo(qr));
		qrDestroy(qr);
		qr = nullptr;
		return resultVec;
	}

	resultVec.resize(size);
	errno_t errno = memcpy_s(&resultVec[0], resultVec.size(), buffer, size);

	free(buffer);
	buffer = nullptr;

	qrDestroy(qr);
	qr = nullptr;

	if (errno != 0)
	{
		SetErr("copy data failed.");
	}

	return resultVec;
}

const std::string QrEncode::GetErr()
{
	return mstrErr;
}

void QrEncode::SetErr(std::string strErr)
{
	mstrErr = strErr;
}
